// Copyright 2022 jeff.li. and/or its affiliates.

#pragma once

#include <type_traits>


namespace tbir::runtime::details {
    template<class Iterable>
    struct generic_enumerate : private Iterable {
        int64_t pos = 0;

        generic_enumerate() {
        }

        generic_enumerate(Iterable seq, int64_t first) : Iterable(seq), pos(first) {
        }

        bool HasNext() const {
            return Iterable::HasNext();
        }

        auto Next() {
            return std::make_pair(pos++, Iterable::Next());
        }

        auto Next(bool *has_next) {
            return std::make_pair(pos++, Iterable::Next(has_next));
        }
    };

}  // namespace tbir::runtime::details

namespace tbir::runtime {
    template<class Iterable>
    details::generic_enumerate<
            typename std::remove_cv<typename std::remove_reference<Iterable>::type>::type>
    generic_enumerate(Iterable &&seq, long first = 0L) {
        return {std::forward<Iterable>(seq), first};
    }

}  // namespace tbir::runtime
